package com.lemontree.common.utils.email;

import com.lemontree.common.utils.Contants;
import com.lemontree.common.utils.SpringContextUtil;
import com.lemontree.common.utils.StringUtil;
import com.lemontree.common.utils.redis.RedisManager;
import com.lemontree.web.entity.EmailConfig;
import com.lemontree.web.service.EmailConfigService;
import org.apache.log4j.Logger;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author: YLBG-YCY-1325
 * @Description:
 * @Date: 2017/3/23
 */
public class EmailUtils {
    private static Logger LOG = Logger.getLogger(EmailUtils.class);
    /** 发送邮箱协议 的key */
    private static final String PROTOCAL_KEY = "mail.transport.protocol";
    /** 发送邮箱主机 的key */
    private static final String HOST_PORT_KEY = "mail.smtp.host";
    /** 发送邮箱主机的端口号 的key */
    private static final String SEND_HOST_KEY = "mail.smtp.port";
    /** 是否进行验证 */
    private static final String EMAIL_AUTH = "mail.smtp.auth";
    /** 邮箱校验正则 */
    public static final String REG = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";

    // redis存储邮箱验证码的时间,暂定为60秒，单位：秒
    public static final int REDIS_EMAIL_SECONDS = 60;
    public static final int REDIS_EMAIL_MINUTES = 5 * 60;
    // 邮箱验证码在redis中的key（存在60秒）
    public static final String EMAIL_CODE_KEY = "emailCode";
    // 邮箱验证码在redis中的key（存在5分钟）
    public static final String EMIAL_CODE_EXIST = "emailCodeExist";

    // 获取邮箱配置信息
    private static EmailConfigService emailConfigService;

    static {
        emailConfigService = (EmailConfigService) SpringContextUtil.getBean("emailConfigService");
    }

    public static void sendEmail(String receiveEmail, String emailCode) throws Exception {
        try {
            if (null == emailConfigService) {
                emailConfigService = (EmailConfigService) SpringContextUtil
                        .getBean("emailConfigService");
            }
            EmailConfig emailConfigs = emailConfigService.getEmailConfigs();
            EmailTemplate emailTemplate = new EmailTemplate();
            emailTemplate.setSubject(emailConfigs.getSendNickName());
            emailTemplate.setText(emailConfigs.getText() + emailCode);
            emailTemplate.setNickName(emailConfigs.getSendNickName());
            sendEmail(emailConfigs.getSendEmail(), emailConfigs.getSendPwd(), receiveEmail,
                    emailConfigs.getProtocal(), emailConfigs.getHostPort(),
                    emailConfigs.getSendHost(), emailTemplate);
        } catch (Exception e) {
            LOG.error("发送邮件异常 -> 错误信息 ->" + e);
            throw e;
        }
    }

    /**
     * 发送简单邮件方法
     * @param mailSender 发送邮箱
     * @param mailSenderPwd 发送邮箱授权码
     * @param mailReceiver 接受邮箱
     * @param protocal 协议
     * @param port 端口
     * @param sendHost 发送者主机
     * @param template 发送模板
     * @throws UnsupportedEncodingException
     * @throws MessagingException
     */
    public static void sendEmail(String mailSender, String mailSenderPwd, String mailReceiver,
            String protocal, Integer port, String sendHost, EmailTemplate template)
            throws UnsupportedEncodingException, MessagingException {

        // 获取配置信息
        Properties properties = getEmailBasicInfo(protocal, port, sendHost);
        // 配置session
        Session session = Session.getDefaultInstance(properties);
        // 获取邮件信息
        MimeMessage message = createMimeMessage(session, mailSender, mailReceiver, template);
        // 通过sesion获取传输信息（配置信息放入session中）
        Transport transport = session.getTransport();
        // 通过主机连接（登录）发送着邮箱
        transport.connect(sendHost, mailSender, mailSenderPwd);
        // 发送邮箱信息
        transport.sendMessage(message, message.getAllRecipients());
        // 关闭传输流
        transport.close();
    }

    /**
     * 邮箱发送信息配置
     * @param protocal smtp协议
     * @param port 端口
     * @param sendHost 发送主机
     * @return 配置信息
     */
    private static Properties getEmailBasicInfo(String protocal, Integer port, String sendHost) {
        Properties properties = new Properties();
        // 协议
        properties.setProperty(PROTOCAL_KEY, protocal);
        // 发送主机
        properties.setProperty(SEND_HOST_KEY, sendHost);
        // 端口号配置
        properties.put(HOST_PORT_KEY, port);
        // 是否进行验证：true：验证
        properties.setProperty(EMAIL_AUTH, "true");
        return properties;
    }

    /**
     * 支持对单个人发送邮箱，后期可以改为发送多个人的邮箱（改InternetAddress[]）
     * @param session 邮件的session
     * @param mailSender 发送邮箱
     * @param mailReceiver 接受者邮箱
     * @param template 邮件模板
     * @return MimeMessage 邮件发送信息
     * @throws MessagingException
     * @throws UnsupportedEncodingException
     */
    private static MimeMessage createMimeMessage(Session session, String mailSender,
            String mailReceiver, EmailTemplate template)
            throws MessagingException, UnsupportedEncodingException {
        MimeMessage message = new MimeMessage(session);
        InternetAddress[] receiveMail = new InternetAddress[1];
        receiveMail[0] = new InternetAddress(mailReceiver);

        // 接受对象
        message.setRecipients(Message.RecipientType.TO, receiveMail);
        // 发送源
        message.setFrom(new InternetAddress(mailSender, template.getNickName(), Contants.CHARSET));

        message.setSubject(template.getSubject(), Contants.CHARSET);
        // 发送内容
        message.setContent(template.getText(), "text/html;charset=" + Contants.CHARSET);
        // 发送日期
        message.setSentDate(new Date());
        return message;
    }

    /**
     * 验证邮箱格式
     * @param email 接收邮箱
     * @return false:邮箱格式错误；true：邮箱格式正确
     */
    public static boolean validatEmail(String email) {
        if (StringUtil.isBlank(email)) {
            return false;
        }
        Pattern p = Pattern.compile(REG);
        Matcher matcher = p.matcher(email);
        return matcher.matches();
    }

    /**
     * 60秒验证
     * @param receiveEmail 接收的邮箱
     * @return true:邮箱可以发送邮箱验证码；false：不可以
     * @throws Exception
     */
    public static boolean validateEmialCode(String receiveEmail) throws Exception {
        if (!validatEmail(receiveEmail)) {
            return false;
        }
        // 判断是60秒内重复发送的
        if (StringUtil
                .isNotBlank(RedisManager.getString(EmailUtils.EMAIL_CODE_KEY + receiveEmail))) {
            return false;
        }
        return true;
    }
}
